<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Tasks;

use Srv\Libs\Frame\ResponseMain;
use Srv\Libs\Frame\TaskAbstract;
use Swoole\Coroutine;
use Swoole\WebSocket\Server;

final class SocksSendTask extends TaskAbstract
{
    private int $delayTimeMill                      = 0;    // 发送延迟时长[毫秒]
    private int $recvReTryNumMax                    = 8;    // 回复重试最大次数
    private int $recvWaitTimeOutMax                 = 4;    // 回复超时最大时长[秒]
    private array $sendTaskDataList                 = [];   // 发送数据任务列表
    private const PUSH_BINARY_BY_USERID             = 1;
    private const PUSH_TEXT_BY_USERID               = 2;
    private const PUSH_BINARY_ALL                   = 3;
    private const PUSH_TEXT_ALL                     = 4;
    private const PUSH_BINARY_BY_LOGIN              = 5;
    private const PUSH_TEXT_BY_LOGIN                = 6;
    private const PUSH_BINARY_BY_PLATFORM           = 7;
    private const PUSH_TEXT_BY_PLATFORM             = 8;
    private const PUSH_BINARY_BY_LANG               = 9;
    private const PUSH_TEXT_BY_LANG                 = 10;
    private const PUSH_BINARY_BY_DEVID              = 11;
    private const PUSH_TEXT_BY_DEVID                = 12;
    private const PUSH_BINARY_BY_GROUP              = 13;
    private const PUSH_TEXT_BY_GROUP                = 14;
    private const PUSH_BINARY_BY_SUBKEY             = 15;
    private const PUSH_TEXT_BY_SUBKEY               = 16;

    /**
     * @param string $envStr
     * @param int $delayTimeMill
     * __construct
     */
    public function __construct(string $envStr, int $delayTimeMill)
    {
        $this->envStr           = $envStr;
        $this->delayTimeMill    = min(max($delayTimeMill, 0), 86400*1000);
    }

    /**
     * @param string $envStr
     * @param int $delayTimeMill
     * @return static
     * create
     */
    public static function create(string $envStr = '', int $delayTimeMill = 0):self
    {
        $__class__              = self::class;
        return new $__class__($envStr, $delayTimeMill);
    }

    /**
     * @param array $userIdList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByUserId
     */
    public function sendBinaryByUserId(array $userIdList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_USERID, $userIdList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $userIdList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByUserId
     */
    public function sendTextByUserId(array $userIdList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_USERID, $userIdList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryAll
     */
    public function sendBinaryAll(string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_ALL, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextAll
     */
    public function sendTextAll(string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_ALL, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param bool $isLogin
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByLogin
     */
    public function sendBinaryByLogin(bool $isLogin, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_LOGIN, $isLogin, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param bool $isLogin
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByLogin
     */
    public function sendTextByLogin(bool $isLogin, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_LOGIN, $isLogin, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $platformList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByPlatform
     */
    public function sendBinaryByPlatform(array $platformList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_PLATFORM, $platformList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $platformList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByPlatform
     */
    public function sendTextByPlatform(array $platformList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_PLATFORM, $platformList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $langList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByLang
     */
    public function sendBinaryByLang(array $langList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_LANG, $langList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $langList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByLang
     */
    public function sendTextByLang(array $langList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_LANG, $langList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $devIdList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByDevId
     */
    public function sendBinaryByDevId(array $devIdList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_DEVID, $devIdList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $devIdList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByDevId
     */
    public function sendTextByDevId(array $devIdList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_DEVID, $devIdList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $groupList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryByGroup
     */
    public function sendBinaryByGroup(array $groupList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_GROUP, $groupList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $groupList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextByGroup
     */
    public function sendTextByGroup(array $groupList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_GROUP, $groupList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $subKeyList
     * @param string $binaryStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendBinaryBySubKey
     */
    public function sendBinaryBySubKey(array $subKeyList, string $binaryStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_BINARY_BY_SUBKEY, $subKeyList, $binaryStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param array $subKeyList
     * @param string $textStr
     * @param array $fdNotList
     * @param int $delayTimeMill
     * @param int $recvReTryNum
     * @param int $recvWaitTimeOut
     * @param int $ackNum
     * @return $this
     * sendTextBySubKey
     */
    public function sendTextBySubKey(array $subKeyList, string $textStr, array $fdNotList = [], int $delayTimeMill = 0, int $recvReTryNum = 0, int $recvWaitTimeOut = 2, int $ackNum = 0):self
    {
        if($this->isTask()) return $this;
        $this->sendTaskDataList[] = [self::PUSH_TEXT_BY_SUBKEY, $subKeyList, $textStr, $fdNotList, $delayTimeMill, min(max($recvReTryNum, 0), $this->recvReTryNumMax), min(max($recvWaitTimeOut, 0), $this->recvWaitTimeOutMax), $ackNum];
        return $this;
    }

    /**
     * @param Server|null $WebSocketServer
     * @return void
     * runBefore
     */
    public function runBefore(?Server $WebSocketServer): void
    {
    }

    /**
     * @param Server|null $WebSocketServer
     * @return void
     * run
     */
    public function run(?Server $WebSocketServer): void
    {
        if(!($WebSocketServer instanceof Server)) return;
        if($this->delayTimeMill > 0) Coroutine::sleep($this->delayTimeMill/1000);
        if(count($this->sendTaskDataList) < 1) return;
        foreach ($this->sendTaskDataList as $taskData){
            switch($taskData[0]){
                case self::PUSH_BINARY_BY_USERID    :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByUserIdMulti($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_USERID    :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByUserIdMulti($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_ALL          :{
                    if($taskData[3] > 0) Coroutine::sleep($taskData[3]/1000);
                    ResponseMain::pushBinaryAll($taskData[1], $taskData[2], $taskData[4], $taskData[5], $taskData[6]);
                    break;
                }
                case self::PUSH_TEXT_ALL            :{
                    if($taskData[3] > 0) Coroutine::sleep($taskData[3]/1000);
                    ResponseMain::pushTextAll($taskData[1], $taskData[2], $taskData[4], $taskData[5], $taskData[6]);
                    break;
                }
                case self::PUSH_BINARY_BY_LOGIN     :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByLogin($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_LOGIN       :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByLogin($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_BY_PLATFORM  :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByPlatform($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_PLATFORM    :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByPlatform($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_BY_LANG      :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByLang($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_LANG        :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByLang($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_BY_DEVID     :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByDevId($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_DEVID       :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByDevId($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_BY_GROUP     :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryByGroup($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_GROUP       :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextByGroup($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_BINARY_BY_SUBKEY    :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushBinaryBySubKey($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
                case self::PUSH_TEXT_BY_SUBKEY      :{
                    if($taskData[4] > 0) Coroutine::sleep($taskData[4]/1000);
                    ResponseMain::pushTextBySubKey($taskData[1], $taskData[2], $taskData[3], $taskData[5], $taskData[6], $taskData[7]);
                    break;
                }
            }
        }
    }

    /**
     * @param Server|null $WebSocketServer
     * @return void
     * runAfter
     */
    public function runAfter(?Server $WebSocketServer): void
    {
    }
}